Einbinden der benötigten Bibliotheken
Die Aufgabe besteht in der Darstellung von Daten im Kontext geographischer Karten, z.B. Wahlkreise und der Anteil von Stimmen für bestimmte Parteien und die Arbeitslosenquote in diesen Bezirken.
Im Folgenden wird in die geographische Visualisierung mit R eingeführt. Es werden die Grundlagen zum Darstellen von Daten in geographischem Kontext behandelt sowie an zwei konkreten Beispielen vorgestellt. todo mehr
Die Grundlage zum Zeichnen von geographischen Grenzen bilden die sogenannten Shape-Files. In diesem Format lassen sich Geometriedaten leicht darstellen. In diesem Projekt wird ein Shape-File zur Darstellung der Grenzen der deutschen Bundesländer verwendet. Ein Shape-File ist Dateiformat welches geographische Vektordaten enthält. Es eignet sich unteranderem zum Zeichnen von Grenzen. Dieses Shape-File wird von dem Bundesamt für Kartographie und Geodäsie bereitgestellt. Im Folgenden Code-Ausschnitt wird das Shape-File eingelesen und beispielhaft die darin enthaltenen Daten ausgegeben.
map <- st_read("data/2500_NUTS1.shp", stringsAsFactors=FALSE)
## Reading layer `2500_NUTS1' from data source `/Users/nahkusaidy/Documents/Repositories/GeoVisualisation/data/2500_NUTS1.shp' using driver `ESRI Shapefile'
## Simple feature collection with 16 features and 3 fields
## geometry type: MULTIPOLYGON
## dimension: XY
## bbox: xmin: 3280341 ymin: 5237533 xmax: 3921264 ymax: 6103334
## epsg (SRID): 31467
## proj4string: +proj=tmerc +lat_0=0 +lon_0=9 +k=1 +x_0=3500000 +y_0=0 +ellps=bessel +towgs84=598.1,73.7,418.2,0.202,0.045,-2.455,6.7 +units=m +no_defs
map = st_transform(map,3857)
ggplot(map) + geom_sf()
Neben reinen Shape-Files gibt es in R die Möglichkeit auch todo “realistischere” Karten zu zeichnen. Hier wird beispielhaft eine Karte von Deutschland von OpenStreetMap gezeichnet.
germany_map <- get_map(getbb("Deutschland", base_url = "https://nominatim.openstreetmap.org", featuretype = "country"),maptype = "toner-background")
ggmap(germany_map)
Um die Möglichkeiten der Darstellung von Daten in geographischem Kontext zu demonstrieren werden nun Daten aus einem Datensatz zur Binnenwanderung in Deutschland analysiert und dargestellt. Dieser wird zuerst importiert und die zu visualisierenden Daten in Data Frames verpackt. Die Daten enthalten das Saldo der Binnenwanderung für jedes Bundesland von Deutschen und Ausländern.
binnenwanderung_data <- read_excel("binnenwanderung.xlsx")
## New names:
## * `` -> ...2
states <- map$NUTS_NAME
movement_per_state <- data.frame(matrix(ncol = 16, nrow = 16))
x <- c("NUTS_NAME",sprintf("%s",2003:2017))
colnames(movement_per_state) <- x
movement_per_state_mean <- data.frame(NUTS_NAME = c(1:16), Mean_Migration = c(1:16))
movement_per_state_sum <- data.frame(NUTS_NAME = c(1:16), Sum_Migration = c(1:16))
for(i in 1:length(states)){
index <- which(binnenwanderung_data == states[i], arr.ind = TRUE)[1]+2
row_data = binnenwanderung_data[index,-1:-3]
data_frame_row = c(c(states[i]), row_data)
names(data_frame_row) <- x
movement_per_state[i,] = data_frame_row
movement_per_state_mean$NUTS_NAME[i] = states[i]
movement_per_state_mean$Mean_Migration[i] = mean(as.numeric(as.character(row_data)))
movement_per_state_sum$NUTS_NAME[i] = states[i]
movement_per_state_sum$Sum_Migration[i] = sum(as.numeric(as.character(row_data)))
}
str(movement_per_state)
## 'data.frame': 16 obs. of 16 variables:
## $ NUTS_NAME: chr "Baden-Württemberg" "Bayern" "Berlin" "Brandenburg" ...
## $ 2003 : num 26926 34212 -7043 -498 673 ...
## $ 2004 : num 22055 25695 -9133 742 1131 ...
## $ 2005 : num 15394 29432 -4328 -522 810 ...
## $ 2006 : num 5673 34153 1955 -3045 1371 ...
## $ 2007 : num 10039 31477 7377 -4021 -292 ...
## $ 2008 : num 12840 26151 12958 -4102 222 ...
## $ 2009 : num 1070 15632 18353 -2173 1590 ...
## $ 2010 : num -1604 10746 17990 -1518 852 ...
## $ 2011 : num 1054 15363 15341 -1596 -564 ...
## $ 2012 : num 1880 15486 12134 1252 -378 ...
## $ 2013 : num -1315 14085 8068 4275 -635 ...
## $ 2014 : num -398 6677 2672 8921 -1910 ...
## $ 2015 : num 1273 4011 -4628 12315 -3182 ...
## $ 2016 : num -4388 -1741 7891 9873 920 ...
## $ 2017 : num -5107 6593 -3013 14458 -2916 ...
str(movement_per_state_mean)
## 'data.frame': 16 obs. of 2 variables:
## $ NUTS_NAME : chr "Baden-Württemberg" "Bayern" "Berlin" "Brandenburg" ...
## $ Mean_Migration: num 5693 17865 5106 2291 -154 ...
Diese Daten werden aufgesplittet in neue und alte Bundesländer, wobei Berlin als altes Bundesland gezählt wird, da im Datensatz nicht zwischen West- und Ostberlin unterschieden wird.
new_states = c("Brandenburg","Mecklenburg-Vorpommern","Sachsen","Sachsen-Anhalt","Thüringen")
new_states_movement = movement_per_state[movement_per_state$NUTS_NAME %in% new_states,]
new_states_movement = new_states_movement[1:5,]
data_of_new_states = colSums(new_states_movement[,-1])
`%notin%` <- Negate(`%in%`)
old_states_movement = movement_per_state[movement_per_state$NUTS_NAME %notin% new_states,]
old_states_movement = old_states_movement[1:11,]
data_of_old_states = colSums(old_states_movement[,-1])
Im Folgenden wird der Vergleich des Saldos der Binnenwanderung zwischen den neuen und alten Bundesländern zwischen 2003 und 2017 in einem Plot dargestellt.
Es ist zu erkennen, dass die Abwanderung von Einwohnern von Ost- nach Westdeutschland bis 2013 immer weiter abgenommen hat. Danach kam es 2014 erstmals zu einer Abwanderung von Einwohnern von West- nach Ostdeutschland.
Eine geographische Darstellung des Durchschnitts des Saldos der Binnenwanderung je Bundesland lässt sich mit folgendem Code realisieren.
ggmap_bbox <- function(map) {
# Extract the bounding box (in lat/lon) from the ggmap to a numeric vector,
# and set the names to what sf::st_bbox expects:
map_bbox <- setNames(unlist(attr(map, "bb")),
c("ymin", "xmin", "ymax", "xmax"))
# Coonvert the bbox to an sf polygon, transform it to 3857,
# and convert back to a bbox (convoluted, but it works)
bbox_3857 <- st_bbox(st_transform(st_as_sfc(st_bbox(map_bbox, crs = 4326)), 3857))
# Overwrite the bbox of the ggmap object with the transformed coordinates
attr(map, "bb")$ll.lat <- bbox_3857["ymin"]
attr(map, "bb")$ll.lon <- bbox_3857["xmin"]
attr(map, "bb")$ur.lat <- bbox_3857["ymax"]
attr(map, "bb")$ur.lon <- bbox_3857["xmax"]
map
}
germany_map <- ggmap_bbox(germany_map)
merged_movement_mean <- left_join(map,movement_per_state_mean,by="NUTS_NAME")
ggmap(germany_map) + coord_sf(crs=st_crs(3857)) + geom_sf(data=merged_movement_mean, aes(fill= Mean_Migration), inherit.aes = FALSE,alpha=0.5)+
scale_fill_gradient2(low= "#CC0033", mid="white",high = "#006633") + ggtitle("Durchschnitt des Saldos der Binnenwanderung in Deutschland")
Das gesamte Saldo von 2013 bist 2017 ist im nächsten Plot dargestellt.
merged_movement_sum<- left_join(map,movement_per_state_sum,by="NUTS_NAME")
ggmap(germany_map) + coord_sf(crs=st_crs(3857)) + geom_sf(data=merged_movement_sum, aes(fill= Sum_Migration), inherit.aes = FALSE,alpha=0.7)+
scale_fill_gradient2(low= "#CC0033", mid="white",high = "#006633") + ggtitle("Summe des Saldos der Binnenwanderung in Deutschland")
Hier fehlt noch plot von kumuliert auf 5 jahre oder so.
votes <- read.csv(file="btw17_kerg.csv", sep=";")
extracted_votes <- data.frame(Votes = votes$X.16, VotesAfD = votes$X.44)
extracted_votes$Votes <- as.numeric(as.character(extracted_votes$Votes))
extracted_votes$VotesAfD <- as.numeric(as.character(extracted_votes$VotesAfD))
extracted_votes$PercentageAfD <- (extracted_votes$VotesAfD/extracted_votes$Votes)*100
votes_per_state <- data.frame(NUTS_NAME = c(1:16), Votes_AfD = c(1:16))
for(i in 1:length(states)){
votes_per_state$NUTS_NAME[i] = states[i]
votes_per_state$Votes_AfD[i] <- extracted_votes$PercentageAfD[which(votes == states[i], arr.ind = TRUE)]
}
income <- read.csv(file="Stimmenanzahl2.csv", sep=";", colClasses=c("NULL", "NULL", "NULL", NA))
income <- data.frame(NUTS_NAME = map$NUTS_NAME, NETTOEINKOMMEN = income)
Im Folgenden wird das durchschnittliche Einkommen und der Stimmenanteil der AfD pro Bundesland in Deutschland dargestellt
merged_stimmen <- left_join(map,votes_per_state,by="NUTS_NAME")
merged_einkommen <- left_join(map,income,by="NUTS_NAME")
plot_stimmen <- ggmap(germany_map) + coord_sf(crs=st_crs(3857)) + geom_sf(data=merged_stimmen, aes(fill= Votes_AfD), inherit.aes = FALSE,alpha=0.7)+
scale_fill_gradient2("Stimmenanteil der AfD",low= "white", high = "#00008B") + ggtitle("Stimmenanteil der AfD")
plot_einkommen <- ggmap(germany_map) + coord_sf(crs=st_crs(3857)) + geom_sf(data=merged_einkommen, aes(fill= Nettoeinkommen), inherit.aes = FALSE,alpha=0.7)+
scale_fill_gradient2("Nettoeinkommen",low= "white", high = "#00008B") + ggtitle("Durchschnittliches Einkommen")
grid.arrange(plot_stimmen, plot_einkommen, nrow=2)
Korrelation des Durchschnittseinkommens mit dem Wahlergebnis pro Bundesland korreliert. Zum Schluss wird hier die
x <- votes_per_state[,2]
y <- income[,2]
plot(x,y,xlab = "Stimmen für die AFD in %", ylab = "Durchschnittliches Einkommen in €")
cor.test(x,y,method="pearson")
##
## Pearson's product-moment correlation
##
## data: x and y
## t = -3.5337, df = 14, p-value = 0.003306
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## -0.8820924 -0.2894141
## sample estimates:
## cor
## -0.6866149